package org.idea.irpc.framework.core.tolerant.impl;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 初始阶段：30 个任务被提交到线程池，但信号量只允许 10 个线程同时执行。
 * 并发控制：前 10 个线程获取许可后执行save data操作并休眠 5 秒，剩余 20 个线程阻塞等待。
 * 许可释放：每有一个线程休眠结束并释放许可，等待队列中的线程立即获取许可并执行。
 * 最终结果：所有 30 个任务分 3 批（每批 10 个）执行，总耗时约 15 秒。
 * @Author linhao
 * @Date created in 6:33 下午 2022/3/2
 */
public class SemaphoreTest {

    private static final int Thread_Count = 30;//使用固定大小为 30 的线程池，意味着最多可以同时执行 30 个线程

    private static ExecutorService executorService = Executors.newFixedThreadPool(Thread_Count);
    //创建一个许可数量为 10 的信号量（new Semaphore(10)），表示最多允许 10 个线程同时访问资源,控制并发访问的线程上限
    private static Semaphore semaphore = new Semaphore(10);

    /**
     * 使用 Java 的Semaphore（信号量）实现并发控制，确保同一时间最多只有 10 个线程可以执行关键代码段
     *
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < Thread_Count; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 获取资源，若此时资源被用光，则阻塞，直到有线程归还资源
                        //每个线程执行时先调用semaphore.acquire()获取许可
                        semaphore.acquire();
                        System.out.println("save data "+System.currentTimeMillis());
                        Thread.sleep(5000);// 模拟耗时操作
                        //执行完成后调用semaphore.release()归还许可
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();
    }
}
